﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace Streaming_Service.Test {
    using NUnit.Framework;

    using Streaming_Service.Enum;
    using Streaming_Service.Media;
    using Streaming_Service.SQL_Ting;
    using Streaming_Service.User;

    [TestFixture]
    public class TestRating {
        private RentIt11 client;

        private string password;

        [SetUp]
        public void SetUp() {
            client = new RentIt11();
        }

        [Test]
        public void Ratings() {
            var session = this.CreateTestAccount();
            var movie = TestMovie.RandomMovie();
            var rating = this.RandomRating();
            var comment = DBFunc.RandStr(10);

            var re = new RatingEntry { Comment = comment, MovieId = movie.Id, UserId = session.UserId };

            Assert.That(!client.RateMovie(null, null));
            Assert.That(!client.RateMovie(new UserSession(), null));
            Assert.That(!client.RateMovie(session, null));
            Assert.That(!client.RateMovie(session, new RatingEntry()));
            Assert.That(client.RateMovie(session, re));
            Assert.That(client.RateMovie(session, re));

            rating = this.RandomRating();
            comment = DBFunc.RandStr(10);
            re.Rating = rating;
            re.Comment = comment;
            Assert.That(!client.EditRating(null, re));
            Assert.That(!client.EditRating(new UserSession(), re));
            Assert.That(!client.EditRating(session, null));
            Assert.That(client.EditRating(session, re));

            var ratings = client.ListRatings();
            Assert.That(ratings.Count > 0);
            Assert.That(ratings.Exists(
                    r =>
                    r.UserId == session.UserId && r.MovieId == movie.Id && r.Rating == rating && r.Comment == comment));

            var userRatings = client.ListUserRatings(session.UserId);
            Assert.That(userRatings.Count > 0);
            Assert.That(userRatings.Exists(
                    r =>
                    r.UserId == session.UserId && r.MovieId == movie.Id && r.Rating == rating && r.Comment == comment));
            Assert.That(client.ListUserRatings(-1).Count == 0);

            var movieRatings = client.ListMovieRatings(movie.Id);
            Assert.That(movieRatings.Count > 0);
            Assert.That(movieRatings.Exists(
                    r =>
                    r.UserId == session.UserId && r.MovieId == movie.Id && r.Rating == rating && r.Comment == comment));
            Assert.That(client.ListMovieRatings(-1).Count == 0);

            Assert.That(!client.DeleteRating(null, -1));
            Assert.That(!client.DeleteRating(new UserSession(), movie.Id));
            Assert.That(!client.DeleteRating(session, -1));
            Assert.That(client.DeleteRating(session, movie.Id));

            Assert.That(client.DeleteAccount(session, password) == UserReturnCode.Success);
        }

        private Rating RandomRating() {
            var r = DBFunc.Rand(0, 5);
            switch(r) {
                case 0:
                    return Rating.Zero;
                case 1:
                    return Rating.One;
                case 2:
                    return Rating.Two;
                case 3:
                    return Rating.Three;
                case 4:
                    return Rating.Four;
                case 5:
                    return Rating.Five;
                default:
                    return Rating.Wrong;
            }
        }

        private UserSession CreateTestAccount() {
            var TLDs = new[] { "dk", "com", "se", "no", "co.uk", "de", "sg" };

            var name = DBFunc.RandStr((uint)DBFunc.Rand(5, 10));
            var email = (DBFunc.RandStr((uint)DBFunc.Rand(5, 10)) + "@" + DBFunc.RandStr((uint)DBFunc.Rand(5, 10)) + "." + TLDs[DBFunc.Rand(0, TLDs.Length - 1)]).ToLower();
            password = DBFunc.RandStr((uint)DBFunc.Rand(10, 20));
            var dob = new DateTime(DBFunc.Rand(1970, 1990), DBFunc.Rand(1, 12), DBFunc.Rand(1, 28));

            var r = client.CreateAccount(name, password, email, dob);
            Assert.That(r == UserReturnCode.Success);
            Assert.That(client.Login(email, password) == null);

            var userInfo = client.GetUserInfoByEmail(email);
            var activationCode = client.GetActivationCode(userInfo.Id);
            Assert.That(client.ActivateAccount(userInfo.Id, activationCode));

            var session = client.Login(email, password);
            Assert.That(session != null && session.UserId > 0);

            return session;
        }
    }
}